什么时候可以使用前置声明,使用前置声明有什么限制条件。

您所在的位置:网站首页 什么情况下用thousands of 什么时候可以使用前置声明,使用前置声明有什么限制条件。

什么时候可以使用前置声明,使用前置声明有什么限制条件。

2024-07-11 02:56| 来源: 网络整理| 查看: 265

首先,我们为什么要包括头文件?        问题的回答很简单,通常是我们需要获得某个类型的定义(definition)。那么接下来的问题就是,在什么情况下我们才需要类型的定义, 在什么情况下我们只需要声明就足够了?        问题的回答是当我们需要知道这个类型的大小或者需要知道它的函数签名的时候,我们就需要获得它的定义。

问题剖析(一):假设我们有类型A和类型C,在哪些情况下在A需要C的定义: ①A继承至C ②A有一个类型为C的成员变量 ③A有一个类型为C的指针的成员变量 ④A有一个类型为C的引用的成员变量 ⑤A有一个类型为std::list的成员变量 ⑥A有一个函数,它的签名中参数和返回值都是类型C ⑦A有一个函数,它的签名中参数和返回值都是类型C,它调用了C的某个函数,代码在头文件中 ⑧A有一个函数,它的签名中参数和返回值都是类型C(包括类型C本身,C的引用类型和C的指针类型),并且它会调用另外一个使用C的函数,代码直接写在A的头文件中 ⑨C和A在同一个名字空间里面 ⑩C和A在不同的名字空间里面解析: 1:没有任何办法,必须要获得C的定义,因为我们必须要知道C的成员变量,成员函数。    (继承,必须有基类头文件,不能前置声明) 2:需要C的定义,因为我们要知道C的大小来确定A的大小,但是可以使用Pimpl惯用法来改善这一点。   (有一个类型为C成员变量,必须有基类头文件,不能前置声明) 3,4:不需要,前置声明就可以了,其实3和4是一样的,引用在物理上也是一个指针,它的大小根据平台不同,可能是32位也可能是64位,反正我们不需要知道C的定义就可以确定这个成员变量的大小。   (有一个类型为C的指针或引用的成员变量,前置声明即可) 5:不需要,有可能老式的编译器需要。标准库里面的容器像list, vector,map,在包括一个list,vector,map 类型的成员变量的时候,都不需要C的定义。因为它们内部其实也是使用C的指针作为成员变量,它们的大小一开始就是固定的了,不会根据模版参数的不同而改变。 6:不需要,只要我们没有使用到C。(函数签名中参数和返回值用到类型C,前置声明即可) 7:需要,我们需要知道调用函数的签名。

8:代码解释如下

8.1 参数和返回类型都是C的引用(或指针) C& doToC(C&); C& doToC2(C& c) {return doToC(c);};

        从上面的代码来看,A的一个成员函数doToC2调用了另外一个成员函数doToC,但是无论是doToC2,还是doToC, 它们的参数和返回类型其实都是C的引用(换成指针,情况也一样),引用的赋值跟指针的赋值都是一样,无非就是整形的赋值,所以这里即不需要知道C的大小也没有调用C的任何函数,实际上这里并不需要C的定义。

8.2 随便把其中一个C&换成C,比如像下面的几种示例: 1. C& doToC(C&); C& doToC2(C c) {return doToC(c);}; 2. C& doToC(C); C& doToC2(C& c) {return doToC(c);}; 3. C doToC(C&); C& doToC2(C& c) {return doToC(c);}; 4. C& doToC(C&); C doToC2(C& c) {return doToC(c);};

        无论哪一种,其实都隐式包含了一个拷贝构造函数的调用,比如1中参数c由拷贝构造函数生成,3中doToC的返回值是一个由拷贝构造函数生成的匿名对象。因为我们调用了C的拷贝构造函数,所以以上无论那种情形都需要知道C的定义。

9、10:都一样,我们都不需要知道C的定义,只是10的情况下,前置声明的语法会稍微复杂一些。示例:不同名字空间的前置声明方式!!         (在两个不同名字空间的类型A和C,A是如何使用前置声明来取代直接包括C的头文件的)

A.h #pragma once #include #include #include #include //不同名字空间的前置声明方式!! namespace test1 { class C; } namespace test2 { //用using避免使用完全限定名 using test1::C; class A { public: C useC(C); C& doToC(C&); C& doToC2(C& c) {return doToC(c);}; private: std::list _list; std::vector _vector; std::map _map; C* _pc; C& _rc; }; } C.h #ifndef C_H #define C_H #include namespace test1 { class C { public: void print() {std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3